unit TabelaQGrid;

interface
uses
  TabelaQ, Estado, EstadoGrid, Acao, AcaoGrid, Ambiente, Agente, Classes;

type
  TTabelaQGrid = class (TTabelaQ)
    private
      FTabelaDeFrequencia,
      FTabelaDeEstados    : TStringList;
      FTabelaDeValores    : array of array of Double;
      FListaDeAcao : TList;

      function RetornaIndiceEstado (s : string) : Integer;
    public
      constructor Create (E : TAmbiente; r : TAgente);

      procedure Treina (s : TEstado; a : TAcao; v : Double); override;
      function RetornaValor (s : TEstado; a : TAcao) : Double; override;
      function RetornaMelhorValor (s : TEstado) : Double; override;
      function RetornaMelhorAcao (s : TEstado) : TAcao; override;

      property Estados : TStringList read FTabelaDeEstados;

  end;

implementation
uses
  AmbienteGrid, SysUtils;

{ TTabelaQGrid }

constructor TTabelaQGrid.Create (E : TAmbiente; r : TAgente);
var
  i, j, k : Integer;

  TamanhoX,
  TamanhoY,
  TamanhoAcao : Integer;

  a : TAcaoGrid;
begin
  FListaDeAcao      := TList.Create;
  FTabelaDeEstados  := TStringList.Create;
  FTabelaDeFrequencia  := TStringList.Create;

  for i := 0 to TAcaoGrid.NumeroDeAcoes-1 do
    begin
      a := TAcaoGrid.Create(i);
      FListaDeAcao.Add(a);
    end;
  TamanhoAcao := TAcaoGrid.NumeroDeAcoes;

  SetLength(FTabelaDeValores, 10, TamanhoAcao);

  for i := 0 to 10-1 do
    for k := 0 to TamanhoAcao-1 do
        FTabelaDeValores[i, k] := 0;

  {TamanhoX := TAmbienteGrid(E).TamanhoX;
  TamanhoY := TAmbienteGrid(E).TamanhoY;

  SetLength(FTabelaDeValores, TamanhoX, TamanhoY, TamanhoAcao);

  for i := 0 to TamanhoX-1 do
    for j := 0 to TamanhoY-1 do
      for k := 0 to TamanhoAcao-1 do
        FTabelaDeValores[i, j, k] := 0;}

end;


function TTabelaQGrid.RetornaIndiceEstado(s: string): Integer;
var
  tamAnt, i, k : Integer;
begin
  Result := FTabelaDeEstados.IndexOf(s);

  if Result = -1 then
    begin
      Result := FTabelaDeEstados.Add(s);
      FTabelaDeFrequencia.Add('0');
    end;

  if FTabelaDeEstados.Count > Length (FTabelaDeValores) then
    begin
      tamAnt := Length (FTabelaDeValores);
      SetLength(FTabelaDeValores, FTabelaDeEstados.Count*2, Length (FTabelaDeValores[0]));
      for i := tamAnt to Length (FTabelaDeValores)-1 do
        for k := 0 to Length (FTabelaDeValores[0])-1 do
            FTabelaDeValores[i, k] := 0;
    end;
end;

function TTabelaQGrid.RetornaMelhorAcao(s: TEstado): TAcao;
var
  i : TTipoAcaoGrid;

  melhor : Double;

  sgrid : TEstadoGrid;

  melhorI : TTipoAcaoGrid;

  Ix : Integer;

  ListaAcoes : TList;

begin
  sgrid := TEstadoGrid(s);

  Ix := RetornaIndiceEstado(sgrid.Descricao);

  ListaAcoes := TList.Create;

  melhor := -99999999;
  melhorI := Low (TTipoAcaoGrid);
  for i := Low (TTipoAcaoGrid) to High (TTipoAcaoGrid) do
    begin
      if FTabelaDeValores[Ix,  Integer(i)] >= melhor then
        begin
          melhor := FTabelaDeValores[Ix, Integer(i)];
          melhorI := i;
          ListaAcoes.Add(FListaDeAcao[Integer(melhorI)]);
        end;

    end;

  Result := TAcaoGrid(ListaAcoes[Random(ListaAcoes.Count)]);

  FreeAndNil(ListaAcoes);
end;

function TTabelaQGrid.RetornaMelhorValor(s: TEstado): Double;
var
  i : TTipoAcaoGrid;

  melhor : Double;

  sgrid : TEstadoGrid;

  Ix    : Integer;
begin
  sgrid := TEstadoGrid(s);
  melhor := -99999999;

  Ix := RetornaIndiceEstado(sgrid.Descricao);

  for i := Low (TTipoAcaoGrid) to High (TTipoAcaoGrid) do
    begin
      if FTabelaDeValores[Ix, Integer(i)] > melhor then
        melhor := FTabelaDeValores[Ix, Integer(i)];

    end;

  Result := melhor;
end;

function TTabelaQGrid.RetornaValor(s: TEstado; a: TAcao): Double;
var
  sgrid : TEstadoGrid;
  agrid : TAcaoGrid;

  Ix    : Integer;
begin
  sgrid := TEstadoGrid(s);
  agrid := TAcaoGrid(a);

  Ix := RetornaIndiceEstado(sgrid.Descricao);

  Result := FTabelaDeValores[Ix, Integer(agrid.Tipo)];
end;


procedure TTabelaQGrid.Treina(s: TEstado; a: TAcao; v: Double);
var
  sgrid : TEstadoGrid;
  agrid : TAcaoGrid;

  Ix    : Integer;
begin
  sgrid := TEstadoGrid(s);
  agrid := TAcaoGrid(a);

  Ix := RetornaIndiceEstado(sgrid.Descricao);

  FTabelaDeFrequencia[Ix] := IntToStr(StrToInt(FTabelaDeFrequencia[Ix]) + 1);

  FTabelaDeValores[Ix, Integer(agrid.Tipo)] := (FTabelaDeValores[Ix, Integer(agrid.Tipo)] + v)/StrToInt(FTabelaDeFrequencia[Ix]);

end;

end.
